package reconciliation

import (
	"fmt"
	"parking-lot-go-admin/controller"
	"parking-lot-go-admin/logger"
	"parking-lot-go-admin/model"
	"parking-lot-go-admin/model/cars"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/xuri/excelize/v2"
)

func ImportHandle(c *gin.Context) {
	id := c.Query("id")

	//查询记录
	var reconciliation model.ReconciliationStruct
	exists, _ := model.GetModelDataFirst(
		model.Db,
		reconciliation.TableName(),
		&reconciliation,
		model.QueryOptions{
			Conditions: map[string]interface{}{
				"id": id,
			},
		})

	if !exists {
		return
	}

	//模糊搜索前缀
	prefix := ""
	switch reconciliation.Type {
	case 1:
		prefix = "XQ-%"
	case 2:
		prefix = "BAF-%"
	}

	f, err := excelize.OpenFile("./uploads/" + reconciliation.FilePath)
	if err != nil {
		fmt.Println(err)
		return
	}

	//对账日志
	outFileName := controller.GenerateRandomFileName(".txt")
	var dzLogger = logger.NewLogger("reconciliation", outFileName)
	defer func() {
		// Close the spreadsheet.
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()

	//状态更新
	model.UpdateModelData(
		model.Db,
		reconciliation.TableName(),
		map[string]interface{}{
			"id": reconciliation.Id,
		},
		map[string]interface{}{
			"status": 1,
		},
	)

	// Get value from cell by given worksheet name and cell reference.
	_, err = f.GetCellValue("Sheet1", "B2")
	if err != nil {
		fmt.Println(err)
		return
	}

	// Get all the rows in the Sheet1.
	rows, err := f.GetRows("Sheet1")
	if err != nil {
		fmt.Println(err)
		return
	}

	var data []map[string]interface{}
	var licensePlates []string // 车牌号切片

	for k, row := range rows {
		// Skip header row (assuming it's the first row)
		if k > 0 {
			// Create a map to store values for each row
			rowData := make(map[string]interface{})

			for j, colCell := range row {
				// Assuming the header row has the column names
				// Use the header as the key for the map

				// Correct usage of ColumnNumberToName with error handling
				colName, err := excelize.ColumnNumberToName(j + 1)
				if err != nil {
					fmt.Println(err)
					return
				}

				//提取出车牌列 单独使用
				if colName == "C" && colCell != "" {
					licensePlates = append(licensePlates, colCell)
				}

				rowData[colName] = colCell
			}

			// Append the map to the slice
			data = append(data, rowData)
		}
	}

	var lastInTime string
	shanghaiLocation, _ := time.LoadLocation("Asia/Shanghai")

	for _, v := range data {
		var carOut cars.CarsOutStruct
		if v["C"] != "" {

			inTime := v["G"].(string)
			inDate, _ := time.ParseInLocation("2006-01-02 15:04:05", inTime, shanghaiLocation)
			inTimeDate := time.Date(inDate.Year(), inDate.Month(), inDate.Day(), 0, 0, 0, 0, inDate.Location())

			outTime := v["H"].(string)
			outDate, _ := time.ParseInLocation("2006-01-02 15:04:05", outTime, shanghaiLocation)
			outTimeDate := time.Date(outDate.Year(), outDate.Month(), outDate.Day(), 23, 59, 59, 0, outDate.Location())

			exists, _ := model.GetModelDataFirst(
				model.Db,
				carOut.TableName(),
				&carOut,
				model.QueryOptions{
					Conditions: map[string]interface{}{
						"park_code":      reconciliation.ParkCode,
						"car_number":     v["C"],
						"in_time >= ? ":  inTimeDate,
						"out_time <= ? ": outTimeDate,
					},
				})

			if !exists {
				dzLogger.Info(fmt.Sprintf("%s%s", v["C"], "查询失败,需要人工查询"))
			}

			lastInTime = v["G"].(string)
		}
	}

	startTime, endTime, _ := getLastDayOfMonth(lastInTime)

	//订单总数
	var carOut cars.CarsOutStruct
	count, _ := model.CountModelData(
		model.Db,
		carOut.TableName(),
		model.QueryOptions{
			Conditions: map[string]interface{}{
				"park_code":       reconciliation.ParkCode,
				"out_time >= ?":   startTime,
				"out_time < ? ":   endTime,
				"order_no like ?": prefix,
			},
		})

	//表格 和 数据库条数不一样 反查表格里的数据
	if len(data) != count {
		var carOutData []cars.CarsOutStruct

		if err := model.GetModelData(
			model.Db,
			carOut.TableName(),
			&carOutData,
			model.QueryOptions{
				Conditions: map[string]interface{}{
					"park_code":             reconciliation.ParkCode,
					"car_number not in (?)": licensePlates,
					"order_no like ?":       prefix,
					"out_time >= ?":         startTime,
					"out_time < ? ":         endTime,
				},
			},
		); err != nil {
			fmt.Println("车牌批量查询错误")
		}

		for _, v := range carOutData {
			// 提取差值中的天数
			duration := v.OutTime.Sub(v.InTime)
			days := int(duration.Hours()/24) + 1

			dzLogger.Info(fmt.Sprintf("记录不存在:  车牌号:%s, 实际入场:%s, 实际离场:%s,天数:%d", v.CarNumber, v.InTime, v.OutTime, days))
		}
	}

	//状态更新
	model.UpdateModelData(
		model.Db,
		reconciliation.TableName(),
		map[string]interface{}{
			"id": reconciliation.Id,
		},
		map[string]interface{}{
			"status":        2,
			"out_file_path": outFileName + "_error.log",
		},
	)

	controller.Success(c, "请求成功")
}

func getLastDayOfMonth(dateString string) (string, string, error) {
	// 解析日期字符串
	date, err := time.Parse("2006-01-02 15:04:05", dateString)
	if err != nil {
		return "", "", err
	}

	// 本月第一天
	firstDayOfMonth := time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, date.Location())

	// 找到下个月的第一天
	firstDayOfNextMonth := time.Date(date.Year(), date.Month()+1, 1, 0, 0, 0, 0, date.Location())

	// 格式化本月第一天
	firstDayOfMonthStr := firstDayOfMonth.Format("2006-01-02 15:04:05")

	// 格式化下月第一天
	firstDayOfNextMonthStr := firstDayOfNextMonth.Format("2006-01-02 15:04:05")

	return firstDayOfMonthStr, firstDayOfNextMonthStr, nil
}
